package com.chenyue.cm.user.service.impl;


import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.chenyue.cm.base.service.BaseServiceImpl;
import com.chenyue.cm.base.dao.LcBaseMapper;
import com.chenyue.cm.bean.Success;
import com.chenyue.cm.common.constant.Constants;
import com.chenyue.cm.common.utils.StringUtils;
import com.chenyue.cm.user.dao.*;
import com.chenyue.cm.user.domain.*;
import com.chenyue.cm.user.service.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;


/**
*
* @author chenyue-cm
*/
@Service(value = "JdFreightTemplateService")
public class JdFreightTemplateServiceImpl extends BaseServiceImpl<JdFreightTemplate>  implements JdFreightTemplateService {

	private final JdFreightTemplateMapper jdFreightTemplateMapper;
	@Resource
	private JdMemberAddressMapper jdMemberAddressMapper;
	@Resource
	private JdMemberShoppingCartMapper memberShoppingCartMapper;
	@Resource
	private JdGoodsSpuMapper goodsSpuMapper;
	@Resource
	private JdGoodsSkuMapper goodsSkuMapper;

	public JdFreightTemplateServiceImpl(@Qualifier("jdFreightTemplateMapper") JdFreightTemplateMapper jdFreightTemplateMapper) {
		this.jdFreightTemplateMapper = jdFreightTemplateMapper;
	}

	@Override
	@Resource(name = "jdFreightTemplateMapper")
	public void setBaseMapper(LcBaseMapper<JdFreightTemplate, Serializable> baseMapper) {
		this.baseMapper = baseMapper;
	}

	@Override
	public BigDecimal calculateFeeByTemplateId(String feeFormworkId, String skuWeight, String num, String provinceCode, BigDecimal fee) {
		JdFreightTemplate mFreightTemplate = this.getById(feeFormworkId);
		List<String> codeList = new ArrayList<>();
		if(StringUtils.isNotEmpty(mFreightTemplate.getProvinceCode())){
			String[] code = mFreightTemplate.getProvinceCode().split(",");
			codeList = Arrays.asList(code);
		}
		//模板类型不是通用模版并且收货地址在其范围内,使用该模版计算运费,否则使用通用模版计算运费(通用模版分为按重量计和按件数计)
		if (codeList.size()>0&&codeList.contains(provinceCode)) {
			fee = concreteFee(mFreightTemplate,skuWeight,num,fee);
		}else{
			LambdaQueryWrapper wrapper = new LambdaQueryWrapper();
			if(StringUtils.isNotEmpty(skuWeight)){
				//0-默认模版  1-运费模版
				wrapper.eq("type","0");
				//计费类型:   0 按重量；1按件数
				wrapper.eq("charge_type","0");
				mFreightTemplate = this.getOne(wrapper);
			}else{
				//0-默认模版  1-运费模版
				wrapper.eq("type","1");
				//计费类型:   0 按重量；1按件数
				wrapper.eq("charge_type","1");
				mFreightTemplate = this.getOne(wrapper);
			}
			fee = concreteFee(mFreightTemplate,skuWeight,num,fee);
		}
		return fee;
	}



	/**
	 * 具体计算运费
	 * @param mFreightTemplate
	 * @param skuWeight
	 * @param num
	 * @return
	 */
	private BigDecimal concreteFee(JdFreightTemplate jdFreightTemplate, String skuWeight, String num,BigDecimal fee) {
		//数据初始化
		fee = jdFreightTemplate.getFirstFee();
		BigDecimal firstWeight = jdFreightTemplate.getFirstWeight();
		BigDecimal firstFee = jdFreightTemplate.getFirstFee();
		BigDecimal continueWeight = jdFreightTemplate.getContinueWeight();
		BigDecimal continueFee = jdFreightTemplate.getContinmeFee();
		//skuWeight不为空按重量计算,否则按件数计算
		if(StringUtils.isNotEmpty(skuWeight)){
			BigDecimal totalWeight = new BigDecimal(skuWeight).multiply(new BigDecimal(num));
			money(firstWeight,firstFee,continueWeight,continueFee,totalWeight);
			//不超过首重或者超出额小于阶梯增重额,直接返回首重运费
			if(totalWeight.compareTo(firstWeight)>0&&totalWeight.subtract(firstWeight).compareTo(continueWeight)>0){
				fee = money(firstWeight, firstFee, continueWeight, continueFee, totalWeight);
			}
		}else{
			//总件数
			BigDecimal totalNum = new BigDecimal(num);
			//不超过首件或者超出额小于阶梯增重额,直接返回首件运费
			if(totalNum.compareTo(firstWeight)>0&&totalNum.subtract(firstWeight).compareTo(continueWeight)>=0){
				fee = money(firstWeight, firstFee, continueWeight, continueFee, totalNum);
			}
		}
		return fee;
	}


	/**
	 * 超过重量、超过件数计算
	 * @param firstWeight  首重【件数】
	 * @param firstFee 首重【件数】 价格
	 * @param continueWeight 阶梯增重【件数】
	 * @param continueFee 阶梯增费
	 * @return
	 */
	private BigDecimal money(BigDecimal firstWeight, BigDecimal firstFee, BigDecimal continueWeight, BigDecimal continueFee, BigDecimal totalWeight) {

		//超过重量【件数】 计算  （总重量【件数】-首重【件数】）/ 阶梯增重【件数】  向上取整

		long concrete = totalWeight.subtract(firstWeight).divide(continueWeight,1, RoundingMode.HALF_UP).setScale( 0, BigDecimal.ROUND_UP ).longValue();
		System.out.println("超出量: "+concrete);
		//超过重量 * 阶梯增费价格 + 首重价格
		BigDecimal money = BigDecimal.valueOf(concrete).multiply(continueFee).add(firstFee);

		return money;
	}

	@Override
	public Success<Object> getFee(String goodsId, String skuId, String cartIds, String num, String addressId) {
		JdMemberAddress mMemberAddress = jdMemberAddressMapper.selectById(addressId);
		BigDecimal fee = new BigDecimal("0");
		if (StringUtils.isNotEmpty(cartIds)) {
			String[] ids = cartIds.split(",");
			for (String id : ids) {
				JdMemberShoppingCart mMemberShoppingCart = memberShoppingCartMapper.selectById(id);
				JdGoodsSku mGoodsSku = goodsSkuMapper.selectById(mMemberShoppingCart.getSkuId());
				JdGoodsSpu mGoodsSpu = goodsSpuMapper.selectById(mMemberShoppingCart.getGoodsId());
				fee = fee.add(calculateFee(mGoodsSpu, mGoodsSku, mMemberShoppingCart.getPurchaseNum().toString(), mMemberAddress.getProvinceName(), fee));
			}
		} else {
			JdGoodsSku mGoodsSku = goodsSkuMapper.selectById(skuId);
			JdGoodsSpu mGoodsSpu = goodsSpuMapper.selectById(goodsId);
			if (mGoodsSku == null || mGoodsSpu == null) {
				return Success.error("商品不存在");
			}
			//合计运费
			fee = calculateFee(mGoodsSpu, mGoodsSku, num, mMemberAddress.getProvinceName(), fee);
		}
		return Success.success(fee);
	}

	/**
	 * 合计运费方法
	 *
	 * @param mGoodsSpu
	 * @param mGoodsSku
	 * @param num
	 */
	private BigDecimal calculateFee(JdGoodsSpu mGoodsSpu, JdGoodsSku mGoodsSku, String num, String
			provinceCode, BigDecimal fee) {
		if (mGoodsSpu.getFeeType().equals(Constants.FEE_TYPE_0)) {
			fee = new BigDecimal(num).multiply(new BigDecimal(mGoodsSpu.getFee()));
		} else {
			fee = this.calculateFeeByTemplateId(mGoodsSpu.getFeeFormworkId(), mGoodsSku.getSkuWeight(), num, provinceCode, fee);
		}
		return fee;
	}
}
